package com.activenetwork.custom;

import java.lang.reflect.Field;

import org.openqa.selenium.support.pagefactory.FieldDecorator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.activenetwork.util.EnvContext;


public class XPageFactory {
	private static Logger logger = LoggerFactory.getLogger(XPageFactory.class);
	private FieldDecorator decorator;
	
	public XPageFactory(FieldDecorator decorator){
		this.decorator = decorator;
	}
			
	public FieldDecorator getDecorator() {
		return decorator;
	}

	public void setDecorator(FieldDecorator decorator) {
		this.decorator = decorator;
	}

	
	
	/**
	 * Initialize the pageObject with input pageObject instance
	 * @param <T>
	 * @param driver
	 * @param pageClassToProxy
	 * @return
	 */
	
	public <T> T initObject(T page){
		logger.trace("Decorate page " + page.getClass().getSimpleName() 
				+ " with " + decorator.getClass().getSimpleName());
		initElements(page);
		return page;
	}
	
	/**
	 * Initialize all the field of one page object 
	 * with @FindBy tag whose type are "MyWebElement"
	 * @param driver
	 * @param page
	 */
	public void initElements(Object page) {
		Class<?> proxyIn = page.getClass();
		while (proxyIn != Object.class) {
			proxyFields(decorator, page, proxyIn);
			proxyIn = proxyIn.getSuperclass();
		}
	}
	/**
	 * The logic to initialize the field whose type are MyWebElement
	 * @param decorator
	 * @param page
	 * @param proxyIn
	 */
	private void proxyFields(FieldDecorator decorator, Object page, Class<?> proxyIn) {
		//Check the thread webdriver instance
		logger.trace(Thread.currentThread().getName() + " - " + EnvContext.webDriverTL.get().toString());
		Field[] fields = proxyIn.getDeclaredFields();
		for (Field field : fields) {
			// Get the field value, if not null then skip
			field.setAccessible(true);
			try {
				Object existValue = field.get(page);
				if(existValue != null) continue;
			} catch (Exception e1) {
				e1.printStackTrace();
			} 
			// Decorate the field by looking for the element on the page
			Object value = decorator.decorate(page.getClass().getClassLoader(), field);	
			if (value != null) {
		        try {
		          field.setAccessible(true);
		          field.set(page, value);
		        } catch (IllegalAccessException e) {
		          throw new RuntimeException(e);
		        } catch (IllegalArgumentException e1){
		        	throw new RuntimeException(e1);	
		        }
		     }
		}
	}
	
	

}
